<script setup lang="ts">

import {
  DataTableBaseColumn,
  DataTableColumns,
  DataTableFilterState,
  DataTableInst,
  FormInst,
  FormItemRule,
  FormRules,
  NButton,
  NButtonGroup,
  NPopconfirm,
  NTag,
  PaginationInfo,
  PaginationProps
} from "naive-ui";
import {SysParam} from "@/api/param/types.ts";
import {renderPermission, resetToNull} from "@/utils";
import {useDictStore} from "@/stores";
import {paramApi} from "@/api/param";

enum ModeTypeEnum {
  ADD = '新增',
  MODIFY = '修改',
  DETAIL = '详情'
}

enum ParamTypeEnum {
  BOOLEAN = 0,
  NUMBER = 1,
  STRING = 2,
  DATETIME = 3,
}

interface PageQuery {
  paramCode: string
  paramType: number
  paramStatus: number
}

const dictStore = useDictStore();
const pageQuery = reactive<PageQuery>(<PageQuery>{})
const tableLoading = ref(false);
const tableRef = ref<DataTableInst | null>(null)
const tableColumns = ref<DataTableColumns<SysParam>>([
  {title: '参数编码', key: 'paramCode', resizable: true},
  {
    title: '参数类型',
    key: 'paramType',
    resizable: true,
    render: row => dictStore.renderTag('param-type', row.paramType),
    filter: true,
    filterMultiple: false,
    filterOptions: dictStore.getDictTextOptions('param-type')
  },
  {title: '参数值', key: 'paramValue', resizable: true},
  {
    title: '参数状态',
    key: 'paramStatus',
    resizable: true,
    render: row => dictStore.renderTag('common-status', row.paramStatus),
    filter: true,
    filterMultiple: false,
    filterOptions: dictStore.getDictTextOptions('common-status')
  },
  {title: '参数描述', key: 'paramDesc', resizable: true},
  {title: '操作', key: 'action', align: 'center', render: row => tableActionRender(row)}
])
const tableData = ref<SysParam[]>([])
const tablePagination = reactive<PaginationProps>({
  prefix: (info: PaginationInfo) => {
    return `共 ${info.itemCount} 条记录`
  },
  showSizePicker: true,
  pageSizes: [10, 20, 50, 100],
  itemCount: 0,
  pageCount: 0,
  onChange: (page: number) => {
    tablePagination.page = page
    handlePageQuery()
  },
  onUpdatePageSize: (pageSize: number) => {
    tablePagination.pageSize = pageSize
    tablePagination.page = 1
    handlePageQuery()
  }
})

const drawerDetailShow = ref(false)
const drawerDetailTitle = ref<ModeTypeEnum | null>(null)
const drawerDetailFormRef = ref<FormInst | null>(null)
const drawerDetailFormModel = reactive<SysParam>(<SysParam>{})
const drawerDetailFormRules = reactive<FormRules>({
  paramCode: {
    required: true,
    trigger: 'blur',
    message: '请输入参数编码'
  },
  paramValue: {
    required: true,
    trigger: 'blur',
    validator: (rule: FormItemRule, value: string) => {
      if (!value) {
        switch (drawerDetailFormModel.paramType) {
          case ParamTypeEnum.BOOLEAN:
            return new Error('请选择布尔值');
          case ParamTypeEnum.NUMBER:
            return new Error('请输入数字');
          case ParamTypeEnum.STRING:
            return new Error('请输入字符串');
          case ParamTypeEnum.DATETIME:
            return new Error('请选择日期');
        }
      }
    }
  }
})
const drawerDetailSubmitLoading = ref(false)

onMounted(() => {
  dictStore.loadDict(['param-type', 'common-status'])
  handlePageQuery()
})
const tableActionRender = (row: SysParam) => {
  return h(NButtonGroup, {size: 'small'}, {
    default: () => [
      renderPermission(h(NButton, {
        tertiary: true,
        onClick: () => handleClickDetail(row)
      }, {default: () => '详情'}), 'param:detail'),
      renderPermission(h(NButton, {
        tertiary: true,
        type: 'primary',
        onClick: () => handleClickModify(row)
      }, {default: () => '修改'}), 'param:modify'),
      h(NPopconfirm, {onPositiveClick: () => handleClickDelete(row)}, {
        trigger: () => renderPermission(h(NButton, {
          tertiary: true,
          type: 'error',
        }, {default: () => '删除'}), 'param:delete'),
        default: () => `确定删除该(${row.paramCode}/${row.paramValue})参数吗？`
      })
    ]
  })
}

const initDrawerDetail = (type: ModeTypeEnum) => {
  drawerDetailTitle.value = type
  drawerDetailShow.value = true
}
const handlePageQuery = () => {
  tableLoading.value = true
  paramApi.page({
    ...pageQuery,
    current: tablePagination.page ?? 1,
    size: tablePagination.pageSize ?? 10
  }).then(res => {
    tableData.value = res.data.records
  }).finally(() => tableLoading.value = false)
}
const handleClickAdd = () => {
  initDrawerDetail(ModeTypeEnum.ADD)
  drawerDetailFormModel.paramType = dictStore.getDictDefault('param-type').dictValue as number
  drawerDetailFormModel.paramStatus = dictStore.getDictDefault('common-status').dictValue as number
}
const handleClickDetail = (row: SysParam) => {
  if (row.id) {
    paramApi.detail(row.id).then(res => {
      Object.assign(drawerDetailFormModel, res.data)
      initDrawerDetail(ModeTypeEnum.DETAIL)
    })
  }
}
const handleClickModify = (row: SysParam) => {
  if (row.id) {
    paramApi.detail(row.id).then(res => {
      Object.assign(drawerDetailFormModel, res.data)
      initDrawerDetail(ModeTypeEnum.MODIFY)
    })
  }
}
const handleClickDelete = (row: SysParam) => {
  if (row.id) {
    paramApi.delete(row.id).then(res => {
      window.$message?.success(res.message)
      handlePageQuery()
    })
  }
}
const handleDrawerClose = () => {
  drawerDetailFormRef.value?.restoreValidation()
  resetToNull(drawerDetailFormModel)
  handlePageQuery()
}
const handleClickSubmit = () => {
  drawerDetailFormRef.value?.validate((errors) => {
    if (!errors) {
      drawerDetailSubmitLoading.value = true
      switch (drawerDetailTitle.value) {
        case ModeTypeEnum.ADD:
          paramApi.add(drawerDetailFormModel).then(res => {
            window.$message?.success(res.message)
            drawerDetailShow.value = false
          })
          break
        case ModeTypeEnum.MODIFY:
          paramApi.modify(drawerDetailFormModel).then(res => {
            window.$message?.success(res.message)
            drawerDetailShow.value = false
          })
          break
      }
    }
  }).finally(() => drawerDetailSubmitLoading.value = false)
}
const handleClickReset = () => {
  resetToNull(pageQuery)
  tableRef.value?.filter(null)
  handlePageQuery()
}
</script>

<template>
  <n-card class="system-param">
    <template #header>
      <n-space>
        <n-input v-model:value="pageQuery.paramCode" placeholder="参数编码" clearable/>
        <n-button
            secondary
            @click="handlePageQuery"
            :loading="tableLoading"
            v-p="'param:page'"
        >查询
        </n-button>
        <n-button
            secondary
            type="primary"
            v-p="'param:add'"
            @click="handleClickAdd">新增
        </n-button>
        <n-button
            secondary
            type="warning"
            @click="handleClickReset">
          重置
        </n-button>
      </n-space>
    </template>
    <n-data-table
        remote
        :loading="tableLoading"
        :columns="tableColumns"
        :data="tableData"
        :pagination="tablePagination"
        :row-key="(row:SysParam) => row.id"
        @update:filters="(filters: DataTableFilterState, {key}: DataTableBaseColumn) => {
          pageQuery[key] = filters[key]
          handlePageQuery()
        }"
    />
  </n-card>
  <n-drawer v-model:show="drawerDetailShow"
            :width="502"
            placement="right"
            :on-after-leave="handleDrawerClose"
            :auto-focus="false"
            :mask-closable="false"
            close-on-esc
  >
    <n-drawer-content :title="drawerDetailTitle" closable>
      <n-form
          ref="drawerDetailFormRef"
          :model="drawerDetailFormModel"
          :rules="drawerDetailFormRules"
          :disabled="drawerDetailTitle === ModeTypeEnum.DETAIL"
      >
        <n-grid :cols="24" :x-gap="12">
          <n-form-item-gi v-if="drawerDetailFormModel.id" :span="24" label="主键">
            <n-tag type="primary">{{ drawerDetailFormModel.id }}</n-tag>
          </n-form-item-gi>
          <n-form-item-gi :span="24" label="参数编码" path="paramCode">
            <n-input v-model:value="drawerDetailFormModel.paramCode" placeholder="请输入参数编码"/>
          </n-form-item-gi>
          <n-form-item-gi :span="24" label="参数类型" path="paramType">
            <n-radio-group size="small"
                           v-model:value="drawerDetailFormModel.paramType"
                           name="paramType"
                           :on-update:value="(value) => {
                              drawerDetailFormModel.paramType = value
                              if (ParamTypeEnum.BOOLEAN === value) {
                                drawerDetailFormModel.paramValue = false
                              } else {
                              drawerDetailFormModel.paramValue = null
                              }
                           }"
                           :disabled="drawerDetailTitle !== ModeTypeEnum.ADD">
              <template v-for="item in dictStore.getDictList('param-type')">
                <n-radio-button :value="item.dictValue" :label="item.dictName"/>
              </template>
            </n-radio-group>
          </n-form-item-gi>
          <n-form-item-gi :span="24" label="参数值" path="paramValue">
            <n-switch v-if="ParamTypeEnum.BOOLEAN === drawerDetailFormModel.paramType"
                      :default-value="false"
                      v-model:value="drawerDetailFormModel.paramValue">
              <template #checked>True</template>
              <template #unchecked>False</template>
            </n-switch>
            <n-input-number v-else-if="ParamTypeEnum.NUMBER === drawerDetailFormModel.paramType"
                            v-model:value="drawerDetailFormModel.paramValue" placeholder="请输入参数值"/>
            <n-date-picker v-else-if="ParamTypeEnum.DATETIME === drawerDetailFormModel.paramType"
                           v-model:value="drawerDetailFormModel.paramValue"
                           type="datetime"
                           placeholder="请选择参数值"/>
            <n-input v-else v-model:value="drawerDetailFormModel.paramValue" placeholder="请输入参数值"/>
          </n-form-item-gi>
          <n-form-item-gi :span="12" label="参数状态" path="paramStatus">
            <n-switch v-model:value="drawerDetailFormModel.paramStatus" :checked-value="1" :unchecked-value="0"/>
          </n-form-item-gi>
          <n-form-item-gi :span="24" label="参数描述" path="paramDesc">
            <n-input type="textarea" v-model:value="drawerDetailFormModel.paramDesc" placeholder="请输入参数描述"/>
          </n-form-item-gi>
        </n-grid>
      </n-form>
      <template v-if="drawerDetailTitle !== ModeTypeEnum.DETAIL" #footer>
        <n-button type="primary"
                  @click="handleClickSubmit"
                  :loading="drawerDetailSubmitLoading"
        >提交
        </n-button>
      </template>
    </n-drawer-content>
  </n-drawer>
</template>

<style scoped>

</style>